package com.bridgeintelligent.tag.webserver.security;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

    protected static final long MILLIS_PER_SECOND = 1000;
    protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
    @Value("${tag.security.login.url:/index.html/#/login}")
    String LOGIN_URL;
    @Value("${tag.security.logout.url:/api/security/logout}")
    String LOGOUT_URL;

    @Bean
    public ExecutorServiceSessionValidationScheduler executorServiceSessionValidationScheduler() {
        ExecutorServiceSessionValidationScheduler sessionValidationScheduler = new ExecutorServiceSessionValidationScheduler();
        sessionValidationScheduler.setInterval(5 * MILLIS_PER_SECOND);
        return sessionValidationScheduler;
    }

    @Bean
    public DefaultWebSessionManager sessionManager(SessionDAO sessionDAO, ExecutorServiceSessionValidationScheduler sessionValidationScheduler) {
        DefaultWebSessionManager sessionManager = new TagWebSessionManager();
        sessionManager.setGlobalSessionTimeout(120 * MILLIS_PER_MINUTE);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationScheduler(sessionValidationScheduler);
        sessionValidationScheduler.setSessionManager(sessionManager);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionDAO(sessionDAO);
        SimpleCookie sessionIdCookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        sessionIdCookie.setHttpOnly(true);
        sessionIdCookie.setMaxAge(-1);
        sessionIdCookie.setName("TAG-SESSION-ID");
        sessionManager.setSessionIdCookie(sessionIdCookie);
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    @Bean
    public SecurityManager securityManager(Collection<Realm> realms, DefaultWebSessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealms(realms);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, PermissionDefinition permissionDefinition, Collection<FilterDefinition> filterDefinitions) {
        TagShiroFilterFactoryBean shiroFilterFactoryBean = new TagShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filters = new LinkedHashMap<>(shiroFilterFactoryBean.getFilters());
        for (FilterDefinition filterDefinition : filterDefinitions) {
            if (null == filterDefinition.getFilter()) {
                continue;
            }
            filters.put(filterDefinition.getName(), filterDefinition.getFilter());
        }

        shiroFilterFactoryBean.setFilters(filters);
        Map<String, String> map = new LinkedHashMap<>(permissionDefinition);
        map.put("/api/engine/**", "anon");
        map.put("/api/batch/**", "anon");
        map.put("/api/security/**", "anon");
        map.put("/api/query/customerDetail/**","anon");
        map.put("/api/provider/**","anon");
        map.put("/api/user/synch/**","anon");
        // map.put("/api/**", "tagAuthc,userSessionFilter");
        map.put("/api/**", "tagAuthc");
        map.put("/**", "anon");
        shiroFilterFactoryBean.setLoginUrl(LOGIN_URL);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
